package com.kedacom.ctsp.authority.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.kedacom.ctsp.authority.constant.AccessLoggerConstant;
import com.kedacom.ctsp.authority.dto.DataAccessDTO;
import com.kedacom.ctsp.authority.dto.FieldDTO;
import com.kedacom.ctsp.authority.entity.Resource;
import com.kedacom.ctsp.authority.entity.ResourceSettingRelation;
import com.kedacom.ctsp.authority.service.ResourceService;
import com.kedacom.ctsp.authority.service.ResourceSettingRelationService;
import com.kedacom.ctsp.authority.vo.ResourceSettingRelationBatchVO;
import com.kedacom.ctsp.authority.vo.ResourceSettingRelationVO;
import com.kedacom.ctsp.authority.vo.ResourceVO;
import com.kedacom.ctsp.lang.mapper.BeanMapper;
import com.kedacom.ctsp.logging.AccessLogger;
import com.kedacom.ctsp.orm.param.Term;
import com.kedacom.ctsp.web.controller.AbstractCrudController2;
import com.kedacom.ctsp.web.controller.message.ResponseMessage;
import com.kedacom.ctsp.web.controller.util.QueryParamUtil;
import com.kedacom.ctsp.web.entity.TreeSupportBean;
import com.kedacom.ctsp.web.entity.param.QueryParamEntity;
import com.kedacom.ctsp.web.service.StatusEnum;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.function.Predicate;
import java.util.stream.Collectors;

import static com.kedacom.ctsp.web.controller.message.ResponseMessage.ok;


/**
 * 资源分配
 *
 * @author sunchenjie
 */
@RequestMapping("resource_setting")
@ResponseBody
@AccessLogger(AccessLoggerConstant.Module.RESOURCE_SETTING)
@Api(tags = "resource-setting", description = "资源分配")
@Slf4j
public class AuthorityResourceSettingController
        extends AbstractCrudController2<ResourceSettingRelation, String, ResourceSettingRelationVO, ResourceSettingRelationService> {

    @Autowired
    private ResourceService resourceService;

    @Override
    public ResponseMessage<String> updateByPrimaryKey(String id, ResourceSettingRelationVO data) {
        return super.patchByPrimaryKey(id, data);
    }


    @GetMapping(path = "/tree/checked")
    @AccessLogger("{query_resource_as_tree}")
    @ApiOperation("按条件获取树形资源")
    @ApiResponses({
            @ApiResponse(code = 200, message = "查询成功"),
            @ApiResponse(code = 401, message = "未授权"),
            @ApiResponse(code = 403, message = "无权限"),
            @ApiResponse(code = 404, message = "数据不存在")
    })
    public ResponseMessage<List<ResourceVO>> listAsTree(QueryParamEntity param, HttpServletRequest request) {
        QueryParamUtil.paddingTerms(param, request);
        // 用户
        Map<String, ResourceSettingRelation> selectedResources = service.select(param).stream()
                .collect(Collectors.toMap(r -> r.getResource().getId(), r -> r));
        String clientSign = "";
        /**
         * 获取项目标识
         */
        if (param.getTerms() != null && param.getTerms().size() > 0) {

            Optional<Term> termClientSign = param.getTerms().stream().filter(t ->
                    t.getColumn().equalsIgnoreCase(ResourceSettingRelation.RESOURCE_CLIENT_SIGN)
            ).findFirst();
            if (termClientSign.isPresent()) {
                clientSign = termClientSign.get().getValue().toString();
            }
        }
        param = new QueryParamEntity();
        param.and(Resource.STATUS, StatusEnum.ENABLE);
        param.setPaging(false);
        param.and(Resource.CLIENT_SIGN, clientSign);
        List<Resource> nodes = resourceService.select(param);
        List<ResourceVO> collect = nodes
                .stream().map(r -> {
                    ResourceVO vo = BeanMapper.deepMap(r, ResourceVO.class);
                    if(r.getField() instanceof String){
                        if(StringUtils.isBlank(r.getField())){
                            r.setField(null);
                        }

                    }
                    Set<FieldDTO> fieldDTOS = JSON.parseObject(r.getField(), new TypeReference<Set<FieldDTO>>() {
                    });
                    if (fieldDTOS != null) {
                        vo.setField(new ArrayList<>(fieldDTOS));
                    }

                    if (selectedResources.containsKey(r.getId())) {
                        vo.setChecked(selectedResources.containsKey(r.getId()));
                        ResourceSettingRelation relation = selectedResources.get(r.getId());
                        // 勾选字段
                        if (StringUtils.isNotBlank(relation.getExcludeFields())) {
                            Set<FieldDTO> excludeFieldsDTOS = JSON.parseObject(relation.getExcludeFields(), new TypeReference<Set<FieldDTO>>() {
                            });
                            if (CollectionUtils.isNotEmpty(fieldDTOS) && CollectionUtils.isNotEmpty(excludeFieldsDTOS)) {
                                fieldDTOS.forEach(e -> {
                                    if (excludeFieldsDTOS.contains(e)) {
                                        e.setChecked(true);
                                    }
                                });
                            }
                        }

                        if (StringUtils.isNotBlank(relation.getDataScope())) {
                            vo.setDataScope((relation.getDataScope()));
                        }
                        if (StringUtils.isNotBlank(relation.getDataAccess())) {
                            List<DataAccessDTO> dataAccessDTOS = JSON.parseObject(relation.getDataAccess(), new TypeReference<List<DataAccessDTO>>() {
                            });
                            vo.setDataAccess(dataAccessDTOS);
                        }
                    }
                    return vo;
                })
                .collect(Collectors.toList());
        List<ResourceVO> results = TreeSupportBean.list2tree(
                collect,
                ResourceVO::setChildren,
                (Predicate<ResourceVO>) entity -> entity.getParent() == null);
        return ok(results);
    }

    /**
     * 批量merge
     *
     * @param batchVO
     * @return
     */
    @PutMapping("/batch")
    @AccessLogger("保存数据,如果数据不存在则新增数据")
    @ApiOperation("保存数据,如果数据不存在则新增数据")
    public ResponseMessage<List<String>> batchSaveOrUpdate(@RequestBody ResourceSettingRelationBatchVO batchVO) {
        ResourceSettingRelationService service = getService();
        if (batchVO != null) {
            // BeanMapper.convertTo 无效
            List<ResourceSettingRelation> rss = BeanMapper.convert(batchVO.getSettings(), this::modelToEntity);
            List<String> ids = service.batchMerge(batchVO.getSettingForType(), batchVO.getSettingForId(), rss);
            return ok(ids);
        }
        return ok();
    }
}
